// Copyright (c) 2009 Christopher Keith (chris.keith@gmail.com)
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.

// Demonstrate simple command lookup in C++.
// dscl < testdata.txt

#include <iostream>
#include <map>
#include <string>
#include <vector>
using namespace std;

struct ltstr {
    bool operator()(const char* s1, const char* s2) const {
        return strcmp(s1, s2) < 0;
    }
};

typedef void(*pt2Func)(vector<string>& tokens);

class Dscl {
public:
            Dscl();
			~Dscl() {}
	void	ProcessInput();

private:
    std::map<const char*, pt2Func, ltstr>    mHandlers; 

	void			Tokenize(const string& str, vector<string>& tokens,
									const string& delimiter);
    void			ProcessLine(char* line);
    static void		Doprint(vector<string>& tokens);
    static void		Reverse(vector<string>& tokens);	   
};

Dscl::Dscl() {
	mHandlers["doprint"] = &Dscl::Doprint;
	mHandlers["reverse"] = &Dscl::Reverse;
}

void Dscl::Doprint(vector<string>& params) {
	vector<string>::iterator iter;
	for (iter = params.begin(); iter != params.end(); iter++ ) {
		cout << *iter << ' ';
	}
	cout << endl;
}

void Dscl::Reverse(vector<string>& params) {
	vector<string>::reverse_iterator iter;
	for (iter = params.rbegin(); iter != params.rend(); iter++ ) {
		cout << *iter << ' ';
	}
	cout << endl;
}

void Dscl::Tokenize(const string& str, vector<string>& tokens, const string& delimiter) {
    string::size_type lastPos = str.find_first_not_of(delimiter, 0);
    string::size_type pos     = str.find_first_of(delimiter, lastPos);

    while (string::npos != pos || string::npos != lastPos) {
        tokens.push_back(str.substr(lastPos, pos - lastPos));
        lastPos = str.find_first_not_of(delimiter, pos);
        pos = str.find_first_of(delimiter, lastPos);
    }
}

void Dscl::ProcessLine(char* line) {
    string			str(line);
    vector<string>	tokens;
	char			d[2];
	d[0] = line[0];
	d[1] = '\0';
	string			delimiter(d);
	Tokenize(str, tokens, delimiter);
	const char*		cmd = tokens[0].c_str();
	vector<string>	params;
	params.assign(tokens.begin() + 1, tokens.end());
	mHandlers[cmd](params);
}


void Dscl::ProcessInput() {
    char    line[81];
	cin.getline(line, 80);
	while ( ! cin.eof()) {
        ProcessLine(line);
		cin.getline(line, 80);
    }
}

int main(int argc, char* argv[]) {
    Dscl    dscl;
    dscl.ProcessInput();
    return 0;
}